using System;
using System.Collections.Generic;
using HtmlAgilityPack;
using RestSharp;
using TripleA.Core.Interfaces;

namespace TripleA.Core.Extensions.Web
{
    public static class WebExtensions
    {

        public static IPipelineConfig<T> CallUri<T>(this IPipelineConfig<T> config, HttpStepConfig stepConfig)
            where T : IWebContext
        {
            config.RunStep(new HttpStep<T>(stepConfig));
            return config;
        } 

        public static IPipelineConfig<T> GetUri<T>(this IPipelineConfig<T> config, string uri)
            where T: IWebContext
        {
            return GetUri(config, uri, null);
        }

        public static IPipelineConfig<T> GetUri<T>(this IPipelineConfig<T> config, Uri uri)
            where T: IWebContext
        {
            return GetUri(config, uri.ToString());
        }

        public static IPipelineConfig<T> GetUri<T>(this IPipelineConfig<T> config, string uri, object args)
            where T: IWebContext
        {
            return GetUri(config, step =>
                                      {
                                          step.Uri = uri;
                                          step.Args = args;
                                      });
        }

        public static IPipelineConfig<T> GetUri<T>(this IPipelineConfig<T> config, Uri uri, object args)
            where T: IWebContext
        {
            return GetUri(config, uri.ToString(), args);
        }

        public static IPipelineConfig<T> GetUri<T>(this IPipelineConfig<T> config, Action<HttpStepConfig> setup)
            where T: IWebContext
        {
            var stepConfig = new HttpStepConfig
                                 {
                                     Method = Method.GET
                                 };

            setup(stepConfig);
            return CallUri(config, stepConfig);
        }

        public static IPipelineConfig<T> PostUri<T>(this IPipelineConfig<T> config, Uri uri, object args)
            where T: IWebContext
        {
            return PostUri(config, uri.ToString(), args);
        }

        public static IPipelineConfig<T> PostUri<T>(this IPipelineConfig<T> config, string uri, object args)
            where T: IWebContext
        {
            return PostUri(config, step =>
                                       {
                                           step.Uri = uri;
                                           step.Args = args;
                                       });
        }

        public static IPipelineConfig<T> PostUri<T>(this IPipelineConfig<T> config, Action<HttpStepConfig> setup)
            where T: IWebContext
        {
            var stepConfig = new HttpStepConfig
                                 {
                                     Method = Method.POST
                                 };

            setup(stepConfig);
            return CallUri(config, stepConfig);
        }


        public static IPipelineConfig<T> AssertHtmlContent<T>(this IPipelineConfig<T> config, string xpath, string expected)
            where T : IWebContext
        {
            config.RunStep(new GetHtmlElementStep<T>
                               {
                                   ElementPath = xpath,
                                   ExpectedCount = 1,
                                   ExpectedText = expected
                               });
            return config;
        }

        public static IPipelineConfig<T> AssertHtmlContent<T>(this IPipelineConfig<T> config, string xpath, int expected)
            where T : IWebContext
        {
            config.RunStep(new GetHtmlElementStep<T>
                               {
                                   ElementPath = xpath,
                                   ExpectedCount =  expected
                               });
            return config;
        }

        public static IPipelineConfig<T> AssertHtmlContent<T>(this IPipelineConfig<T> config, 
            string xpath,
            Predicate<IEnumerable<HtmlNode>> assert)
            where T : IWebContext
        {
            config.RunStep(new GetHtmlElementStep<T>
                               {
                                   ElementPath = xpath,
                                   Assert = assert
                               });
            return config;
        }

        public static IPipelineConfig<T> AssertHtmlContentViaCss<T>(this IPipelineConfig<T> config, string cssSelector, string expected)
            where T : IWebContext
        {
            config.RunStep(new GetHtmlElementStep<T>
                               {
                                   CssSelector = cssSelector,
                                   ExpectedCount = 1,
                                   ExpectedText = expected
                               });
            return config;
        }

        public static IPipelineConfig<T> AssertHtmlContentViaCss<T>(this IPipelineConfig<T> config, string cssSelector, int expected)
            where T : IWebContext
        {
            config.RunStep(new GetHtmlElementStep<T>
                               {
                                   CssSelector = cssSelector,
                                   ExpectedCount = expected
                               });
            return config;
        }

        public static IPipelineConfig<T> AssertHtmlContentViaCss<T>(this IPipelineConfig<T> config,
            string cssSelector,
            Predicate<IEnumerable<HtmlNode>> assert)
            where T : IWebContext
        {
            config.RunStep(new GetHtmlElementStep<T>
                               {
                                   CssSelector = cssSelector,
                                   Assert = assert
                               });
            return config;
        }

    }
}